﻿Imports System.Windows.Controls.Primitives
Imports System.ComponentModel
Imports System.Net
Imports System.IO

Namespace Server
	Public Class RemoteServer
		Implements IDisposable


#Region "Properties and Private Members"

		''' <summary>
		''' The Background worker that manages the HTTP requests and feedback.
		''' </summary>
		''' <remarks></remarks>
		Private WithEvents Worker As BackgroundWorker

		''' <summary>
		''' Gets/Sets whether the server is in the process of ending.
		''' </summary>
		''' <remarks></remarks>
		Private Ending As Boolean = False

		''' <summary>
		''' The listener object responsible for monitoring http requests and feedback.
		''' </summary>
		''' <remarks></remarks>
		Private Listener As HttpListener

		''' <summary>
		''' The port number that must be connected to.
		''' </summary>
		''' <value></value>
		''' <returns></returns>
		''' <remarks></remarks>
		Public ReadOnly Property PortNumber As Integer
			Get
				Return My.Settings.PortNumber
			End Get
		End Property

		''' <summary>
		''' The IP Address that is expected to be connected on.
		''' </summary>
		''' <remarks></remarks>
		Private IPAddress As String

#End Region

#Region "Events"


		Public Event SendCommand(ByVal command As String, ByVal value As String)

#End Region

#Region "Constructors"
		Public Sub New()
			Worker = New BackgroundWorker()
			Worker.WorkerReportsProgress = True
			Worker.WorkerSupportsCancellation = True
		End Sub

#End Region

#Region "WebServr Calls"

		''' <summary>
		''' Starts the WebServr instance.
		''' </summary>
		''' <remarks></remarks>
		Public Sub StartServr()

			Worker.RunWorkerAsync()
			Dim ip As IPAddress() = Dns.GetHostAddresses(Dns.GetHostName)
			For Each ipa As IPAddress In ip
				If ipa.AddressFamily = System.Net.Sockets.AddressFamily.InterNetwork Then
					IPAddress = ipa.ToString()
				End If
			Next
			My.Application.Show.Console.SendMessage("WebServr Started" & vbCr & "Connect to this servr via: http://" & IPAddress & ":" & PortNumber)

		End Sub

		''' <summary>
		''' Stops the WebServr instance.
		''' </summary>
		''' <remarks></remarks>
		Public Sub StopServr()
			Worker.CancelAsync()
			Ending = True
			Listener.Close()
		End Sub

#End Region

#Region "Worker Events"

		Private Sub Worker_DoWork(sender As Object, e As DoWorkEventArgs) Handles Worker.DoWork
			'Create the active listener
			Listener = New HttpListener()

			'Add the port and prefix info
			Listener.Prefixes.Add("http://+:" & My.Settings.PortNumber & "/")
			Try
				Listener.Start()
				Dim HtmlPage As System.IO.TextReader = New System.IO.StreamReader("Server\QRemote.html")
				Dim PageContent As String = HtmlPage.ReadToEnd()
				While Not Worker.CancellationPending
					Dim ListenContext As HttpListenerContext = Listener.GetContext()
					If ListenContext.Request.HttpMethod = "POST" Then
						'This is a POST-back so we're receiving input commands.
						Dim cmd = New StreamReader(ListenContext.Request.InputStream).ReadToEnd()
						ParseCommands(cmd)
						Worker.ReportProgress(1)
					End If
					'Now we need to serve the web page.
					Dim buffer As Byte() = System.Text.Encoding.UTF8.GetBytes(PageContent)
					ListenContext.Response.ContentLength64 = buffer.Length
					ListenContext.Response.OutputStream.Write(buffer, 0, buffer.Length)
					ListenContext.Response.Close()
				End While
				Listener.Stop()
			Catch ex As Exception
				If Not Ending Then
					My.Application.Show.Console.SendMessage("Failed to communicate with client. Using this feature requires running the program as an administrator. This is " & _
															"also a very early implementation of a web service and may not work in all circumstances.", ex)
				End If
			End Try


		End Sub


		Private Sub ParseCommands(cmd As String)
			Dim stringP As String() = cmd.Split("&"c)
			'RemoteCommands.Clear()
			For Each s As String In stringP
				Dim index As Integer = s.IndexOf("="c)
				If index > -1 Then
					Dim key As String = s.Substring(0, index)
					Dim value As String = s.Substring(index + 1)
					value = System.Uri.UnescapeDataString(value)
					'RemoteCommands.Add(key, value)
					Try
						RaiseEvent SendCommand(key, value)
					Catch ex As Exception
						My.Application.Show.Console.SendMessage("There was a problem parsing a command from a remote source.", ex)
					End Try
					My.Application.Show.Console.SendMessage("The message: " & key & " was just received, with the value: " & value)
				End If
			Next
		End Sub


		Private Sub Worker_RunWorkerCompleted(sender As Object, e As RunWorkerCompletedEventArgs) Handles Worker.RunWorkerCompleted
			Ending = False
			My.Application.Show.Console.SendMessage("Remote Access Stopped.")
		End Sub

		Private Sub Worker_ProgressChanged(sender As Object, e As ProgressChangedEventArgs) Handles Worker.ProgressChanged
			'Dim newEA As RoutedEventArgs = New WebServrEventArgs(RemoteCommands)
			'Me.RaiseEvent(newEA)
		End Sub


#End Region




#Region "IDisposable Support"
		Private disposedValue As Boolean ' To detect redundant calls

		' IDisposable
		Protected Overridable Sub Dispose(disposing As Boolean)
			If Not Me.disposedValue Then
				If disposing Then
					Worker.Dispose()
				End If
			End If
			Me.disposedValue = True
		End Sub

		' This code added by Visual Basic to correctly implement the disposable pattern.
		Public Sub Dispose() Implements IDisposable.Dispose
			' Do not change this code.  Put cleanup code in Dispose(disposing As Boolean) above.
			Dispose(True)
			GC.SuppressFinalize(Me)
		End Sub
#End Region

	End Class
End Namespace